#pragma once
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // !WIN32_LEAN_AND_MEAN
#include <common_header.h>
#include <dxgi1_6.h>
#include <d3d12.h>
#include <utl/string.h>

#ifdef _DEBUG
#define DXASSERT(x) assert((x) == S_OK)
#define OBJ_NAME(x,name,...) set_obj_name(x,name,__VA_ARGS__)
#else
#define DXASSERT(x) x
#define OBJ_NAME(x,name,...) void(0)
#endif // _DEBUG

#define DXUPALIGN(A,B) ((((A)+((B)-1))&~((B)-1)))

#define DXCONSTANTALIGN(A) DXUPALIGN(A,D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT)

#define IIDPPV(x) d3d12::get_guid((x)),((void**)(&x))
namespace d3d12
{
	using ID3D12DeviceN = ID3D12Device7;
	using ID3D12GraphicsCommandListN = ID3D12GraphicsCommandList6;
	using IDXGIFactoryN = IDXGIFactory7;
	using IDXGISwapChainN = IDXGISwapChain4;
	using IDXGIAdapterN = IDXGIAdapter4;

	template<typename T>
	constexpr GUID get_guid(T*)
	{
		return __uuidof(T);
	}

	template<typename T>
	void release(T*& obj)
	{
		if (obj != nullptr)
		{
			obj->Release();
			obj = nullptr;
		}
	}

	template <typename T, typename... Args>
	void set_obj_name(T* i, const wchar_t* name, Args&&...args)
	{
		utl::wstring obj_name{ utl::wstring::CtorSprintf(),name,eastl::forward<Args>(args)... };
		DXASSERT(i->SetName(obj_name.c_str()));
	}

	struct descriptor_handle
	{
		D3D12_CPU_DESCRIPTOR_HANDLE cpu;
		D3D12_GPU_DESCRIPTOR_HANDLE gpu;
	};

	template<typename T>
	u64 get_constant_alignment_size()
	{
		static u64 align_size{ DXCONSTANTALIGN(sizeof(T)) };
		return align_size;
	}

	constexpr u32 COMMAND_FRAME_COUNT{ 4u };
	constexpr u32 COMMAND_FRAME_COUNT_1{ COMMAND_FRAME_COUNT - 1u };
}